/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package dao;

import javax.ejb.Stateless;
import javax.*;
import entities.*;
import java.util.*;
import javax.ejb.*;
import javax.persistence.*;
import java.text.*;
//import javax.transaction.Transaction;
import exceptions.*;
import java.io.PrintWriter;
import org.eclipse.persistence.internal.sessions.DirectCollectionChangeRecord.NULL;
/**
 *
 * eCOM - Adopte un Presta - Mars-Avril 2013
 * @author Kheira, Jef, William, Tuan-Long
 */

@Stateless(mappedName = "Interface")
@TransactionAttribute(TransactionAttributeType.REQUIRED)

public class DaoJpa implements IdaoLocal{
    @PersistenceContext
    private EntityManager em;    
    
    
    
    // ------------------------------------------
    // Méthodes pour Account, Commande et Product
    // ------------------------------------------
    
    // liste des comptes
    public List<Account> getAllAccounts() {
        try{
            return em.createQuery("SELECT a FROM Account a").getResultList();            
        } catch(Throwable th){
            throw new AdopteUnPrestaException(th, 1);
        }
    }
    
    // liste des produits (prestataires)
    public List<Product> getAllProducts() {
        try{
            return em.createQuery("SELECT p FROM Product p").getResultList();            
        } catch(Throwable th){
            throw new AdopteUnPrestaException(th);
        }
    }
    
    // Liste des commandes
    public List<Commande> getAllCommandes() {
        try
        {
            return em.createQuery("SELECT c FROM Commande c").getResultList();            
        } catch(Throwable th){
            throw new AdopteUnPrestaException(th, 1);
        }
    }
    
    // liste des comptes par AccessLevel
    public List<Account> getAccountsByAccessLevel(Integer accessLevel){
        try{
            return em.createQuery("SELECT a FROM Account a WHERE a.accessLevel = "+"\""+accessLevel+"\"").getResultList();
        } catch(Throwable th){
            throw new AdopteUnPrestaException(th, 2);
        }
    }
    
    // trouver un compte par son login
    public Account getAccountsByLogin(String login){
        try{
            return (Account) em.createQuery("SELECT a FROM Account a WHERE a.login = "+"\""+login+"\"").getSingleResult();
        } catch(Throwable th){
            throw new AdopteUnPrestaException(th, 3);
        }
    } 
    
     // trouver un compte par son id
    public Account getAccountById(int idAccount){
        try{
            return (Account) em.createQuery("SELECT a FROM Account a WHERE a.idAccount = "+"\""+ idAccount +"\"").getSingleResult();
        } catch(Throwable th){
            throw new AdopteUnPrestaException(th, 3);
        }
    } 
    
    // trouver un compte par son login et password
    public Account getAccountByLoginAndPass(String login, String password) {
        try{
            return (Account) em.createQuery("SELECT a FROM Account a WHERE a.login = "+"\""+login+"\" AND a.password = "+"\""+password+"\"").getSingleResult();
        } catch (NoResultException e) {
            return null;
        }
        catch(Throwable th){
            throw new AdopteUnPrestaException(th, 4);
        }
    }
    
    // Créditer un compte avec un nouveau solde
    public void updateAccountWithSolde(Account a, double added_solde) {
        Double d_added_solde = new Double(added_solde);
        Double arrondi = new Double("0");
        arrondi = (Math.floor(d_added_solde * 100+0.5))/100;
        Double d_arrondi = new Double(arrondi);
        try {
            Query q1 = em.createQuery("UPDATE Account a SET a.solde = a.solde + "+ d_arrondi + " WHERE a.idAccount = \"" + a.getIdAccount() + "\" ");
            int heh = q1.executeUpdate();
        }
        catch(Throwable th) {
            throw new AdopteUnPrestaException("Impossible de créditer le compte.");
        }
    }
    
    // Modifier un compte  
    public void updateAccount(int idAccount, String nom, String prenom, String adresse, double solde, String login, String password, String iban){
        
        System.out.println("id : " +idAccount);
        System.out.println("nom : " +nom);   
        System.out.println("prenom : " +prenom);
        System.out.println("adresse: " +adresse);           
        try {                
            Query q2 = em.createQuery("UPDATE Account a SET a.nom = \""+ nom + "\", a.prenom = \""+ prenom + "\", a.adresse = \""+ adresse + "\", a.solde = \""+ solde + "\", a.login = \""+ login + "\", a.password = \""+ password + "\", a.iban = \""+ iban + "\" WHERE a.idAccount = \""+ idAccount + "\"");
            int modif = q2.executeUpdate(); 
        }
        catch(Throwable th) {
            th.printStackTrace();
            //throw new AdopteUnPrestaException("Impossible de modifier le compte.");
        }
    }
    
    // Met à jour un Product avec un numéro de comande à jour
    public void updateProductWithIdCommande(Product p, int idc) {
        try {
            Query q1 = em.createQuery("UPDATE Product p SET p.commandeidCommande = \""+ idc + "\" WHERE p.idProduct = \"" + p.getIdProduct() + "\" ");
            int heh = q1.executeUpdate();
        }
        catch(Throwable th) {
            th.printStackTrace();
            throw new AdopteUnPrestaException("Impossible de modifier le presta.");
        }
    }

    // liste des commandes d'un utilisateur
    public List<Commande> getAllCommandesOfAccount(int a) 
    {
        try
        {
            return em.createQuery
                    ("SELECT c FROM Commande c WHERE c.accountidAccount = "+"\""+ a +"\"").getResultList();
        }
        catch (Throwable th)
        {
            throw new AdopteUnPrestaException(th, 5);
        }
    }
    
    // Récupère le Product lié à un idCommande
    public Product getProductByIdCommande(int i)
    {
                try
        {
            return (Product) em.createQuery
                    ("SELECT p FROM Product p WHERE p.commandeidCommande = "+"\""+ i +"\"").getSingleResult();
        }
        catch (Throwable th)
        {
            throw new AdopteUnPrestaException(th, 5);
        }
    }
    
    // Récupère le Product lié à son id
    public Product getProductById(int i)
    {
        try
        {
            return (Product) em.createQuery
                    ("SELECT p FROM Product p WHERE p.idProduct = "+"\""+ i +"\"").getSingleResult();
        }
        catch (Throwable th)
        {
            throw new AdopteUnPrestaException(th, 17);
        }
    }
    
    // Récupère le Product lié à son nom et son prenom
    public Product getProductByNometPrenom(String nom, String prenom)
    {
        try
        {
            return (Product) em.createQuery
                    ("SELECT p FROM Product p WHERE p.nom = "+"\""+ nom+"\" AND p.prenom = "+"\""+ prenom+"\"").getSingleResult();
        }
        catch (Throwable th)
        {
            throw new AdopteUnPrestaException(th, 17);
        }
    }
    


    // récupérer le solde d'un compte utilisateur
    public Double getSoldeOfAccount(Account a) {
        try{
            return (Double) em.createQuery("SELECT solde FROM Account a WHERE a.idAccount = "+"\""+a.getIdAccount()+"\"").getSingleResult();
        } catch(Throwable th){
            throw new AdopteUnPrestaException(th, 6);
        }
    }

    // récupérer le numéro IBAN d'un compte utilisateur
    public String getIbanOfAccount(Account a) {
        try{
            return (String) em.createQuery("SELECT IBAN FROM Account a WHERE a.idAccount = "+"\""+a.getIdAccount()+"\"").getSingleResult();
        } catch(Throwable th){
            throw new AdopteUnPrestaException(th, 7);
        }
    }

    // récupérer le CV d'un prestataire
    public Cv getCvOfProduct(Product prestataire) {
        try{
            return (Cv) em.createQuery("SELECT cv FROM CV cv WHERE cv.idCV = "+"\""+prestataire.getCVidCV()+"\"").getSingleResult();
        } catch(Throwable th){
            throw new AdopteUnPrestaException(th, 8);
        }
    }
    
    // Mettre à jour l'état d'un prestataire
    public void updateProductEtat(int idP, String new_etat) {
        try {
            new_etat = "'" + new_etat + "'";
            Query q1 = em.createQuery("UPDATE Product p SET p.etat = "+ new_etat + " WHERE p.idProduct = \"" + idP + "\" ");
            int heh = q1.executeUpdate();
        }
        catch(Throwable th) {
            throw new AdopteUnPrestaException("Impossible de mettre à jour l'état du prestataire.");
        }
    }

    // récupérer le Product store d'un prestataire
    public ProductStore getProductStoreOfProduct(Product prestataire) {
        try{
            return (ProductStore) em.createQuery("SELECT p FROM ProductStore p WHERE p.reference = "+"\""+prestataire.getProductStorereference()+"\"").getSingleResult();
        } catch(Throwable th){
            throw new AdopteUnPrestaException(th, 9);
        }
    }

    // récupérer une commande par son id
    public Commande getCommandeById(Integer id) {
        try{
            return (Commande) em.createQuery("SELECT c FROM Commande c WHERE c.idCommande = "+"\""+id+"\"").getSingleResult();
        } catch(Throwable th){
            throw new AdopteUnPrestaException(th, 10);
        }
    } 
    
    // ajouter un compte utilisateur
    public Account addAccount(int idAccount, String nom, String prenom, String adresse, double solde, String login, String password, int accessLevel, String iban, int idCart) {
        try{ 
            Account account = new Account(idAccount, nom, prenom, adresse, solde, login, password, accessLevel, iban, idCart);
            em.persist(account);
            return account;  
        } catch(Throwable th){
            throw new AdopteUnPrestaException(th, 11);
        }
    }    
    
    // ajouter un produit      
    public Product addProduct(int idProduct, String nom, String prenom, double prix, String description, int idCV, int reference, String etat,  int categorie, int idCommande) {
        try{
            Product prestataire = new Product(idProduct, nom, prenom, prix, description, idCV,reference, etat, categorie, idCommande);
            em.persist(prestataire);     
            return prestataire;
        } catch(Throwable th){ 
            th.printStackTrace();
            throw new AdopteUnPrestaException(th, 12);
        }
    }
    
    // Modifier un Presta (Product)
     public void updatePresta(int idPresta, String nom, String prenom, String description, double prix, int intReference, String etat , int intCategorie){
        try{
            System.out.println("id : " +idPresta);
            System.out.println("nom : " +nom);   
            System.out.println("prenom : " +prenom);      
            System.out.println("description : " +description);   
            System.out.println("prix : " +prix);   
            System.out.println("reference : " + intReference);   
            System.out.println("etat : " +etat);
            System.out.println("categorie : " +intCategorie);   
            
            Query q2 = em.createQuery("UPDATE Product p SET p.nom = \""+ nom + "\", p.prenom = \""+ prenom + "\", p.description = \""+ description + "\", p.prix = \""+ prix + "\", p.productStorereference = \""+ intReference + "\", p.etat = "+ etat + ",p.categorieidCategorie = \""+ intCategorie + "\" WHERE p.idProduct = \""+ idPresta+ "\"");
            int modif = q2.executeUpdate(); 
        }
        catch(Throwable th) {
            th.printStackTrace();
            //throw new AdopteUnPrestaException("Impossible de modifier le compte.");
        }
     }
    
    // ajouter une commande
    public Commande addCommande(Integer idCommande, Integer accountidAccount) {
        try{
            Commande commande = new Commande(idCommande, accountidAccount);
            java.sql.Date sysdate = new java.sql.Date((new java.util.Date()).getTime());
            em.persist(commande);
            Query q2 = em.createQuery("UPDATE Commande c SET c.dateCommande = '"+ sysdate + "'");
            int heh = q2.executeUpdate(); 
            
            return (commande);
        } 
        catch(Throwable th) 
        {
            th.printStackTrace();
            throw new AdopteUnPrestaException("Problème dans l'insertion de la commande.");
        }
    }


    // supprimer un compte utilisateur
    public void deleteAccount(Account a) {
        try{ 
            em.remove(em.merge(a));
        } catch(Throwable th){
            throw new AdopteUnPrestaException(th, 14);
        }
    }

    // supprimer un prestataire
    public void deleteProduct(Product prestataire) {
        try{
            em.remove(em.merge(prestataire));
        } catch(Throwable th){
            throw new AdopteUnPrestaException(th, 15);
        }
    }

    // ------------------------------
    // Méthodes pour Commentaire
    // ------------------------------
    
    // Ajouter un commentaire
    public Commentaire addCommentaire(Integer idCommentaire, String commentaire, String note, Integer productidProduct) {
        try{
            Commentaire comm = new Commentaire(idCommentaire, commentaire, note, productidProduct);
            em.persist(comm);
            return comm;
        } catch(Throwable th){
            throw new AdopteUnPrestaException(th, 16);
        }
    }
    
    // Supprimer un commentaire
    public void deleteCommentaire(Commentaire comm) {
        try{
            em.remove(em.merge(comm));
        } catch(Throwable th){
            throw new AdopteUnPrestaException(th, 17);
        }
    }
    
    // Récupérer un commentaire par son id
    public Commentaire getCommentaireById(Integer id) {
        try{
            return (Commentaire) em.createQuery("SELECT c FROM Commentaire c WHERE c.idCommentaire = "+"\""+id+"\"").getSingleResult();
        } catch(Throwable th){
            throw new AdopteUnPrestaException(th, 18);
        }
    }
    
    // Liste des commentaires d'un prestataire
    public List<Commentaire> getAllCommentairesOfProduct(Product p) {
        try{
            return em.createQuery("SELECT c FROM Commentaire c WHERE c.productidProduct = "+"\""+p.getIdProduct()+"\"").getResultList();
        } catch(Throwable th){
            throw new AdopteUnPrestaException(th, 19);
        }
    }
    
    // ------------------------------
    // Méthodes pour CV
    // ------------------------------
    
    // Ajouter un cv
    public Cv addCv(Integer idCV, Date dateDeNaissance, String situationMatrimoniale,
            String formation, String competences, String experienceProfessionnelle,
            String loisirs) {
        try{
            Cv c_v = new Cv(idCV, dateDeNaissance, situationMatrimoniale, 
                    formation, competences, experienceProfessionnelle,
                    loisirs);
            em.persist(c_v);
            return c_v;
        } catch(Throwable th){
            throw new AdopteUnPrestaException(th, 20);
        }
    }
    
    // Supprimer un cv
    public void deleteCv(Cv c_v) {
        try{
            em.remove(em.merge(c_v));
        } catch(Throwable th){
            throw new AdopteUnPrestaException(th, 21);
        }
    }
    
    // Récupérer un CV par son id
    public Cv getCvById(Integer id) {
        try{
            return (Cv) em.createQuery("SELECT c FROM Cv c WHERE c.idCV = "+"\""+id+"\"").getSingleResult();
        } catch(Throwable th){
            throw new AdopteUnPrestaException(th, 22);
        }
    }    
         
    // ------------------------------------------
    // Méthodes à utiliser avec ProductStore
    // ------------------------------------------
    
    // ajouter un ProductStore
    public ProductStore addProductStore (Integer reference, String nom, String description, String IBAN) {
        try{
            ProductStore entreprise = new ProductStore(reference, nom, description, IBAN);
            em.persist(entreprise);
            return entreprise;
        } catch(Throwable th){
            throw new AdopteUnPrestaException(th, 23);
        }
    }
    
    // Modifier un ProductStore
     public void updateProductStore(int intReference, String nom, String description, String iban){
        try{
            System.out.println("id : " +intReference);
            System.out.println("nom : " +nom);   
            System.out.println("prenom : " +description);
            System.out.println("adresse: " +iban);                         
            Query q2 = em.createQuery("UPDATE ProductStore ps SET ps.nom = \""+ nom + "\", ps.description = \""+ description + "\", ps.iban = \""+ iban + "\" WHERE ps.reference = \""+ intReference+ "\"");
            int modif = q2.executeUpdate(); 
        }
        catch(Throwable th) {
            th.printStackTrace();
            //throw new AdopteUnPrestaException("Impossible de modifier le compte.");
        }
     }
    
    // Supprimer un ProductStore
     public void deleteProductStore(ProductStore ps) {
         try{
             em.remove(em.merge(ps));
         } catch(Throwable th){
            throw new AdopteUnPrestaException(th, 24);
        }
    }
     
    // récupérer la liste des ProductStore
    public List<ProductStore> getAllProductStore() {
        try{
            return em.createQuery("SELECT p FROM ProductStore p").getResultList();
        } catch(Throwable th){
            throw new AdopteUnPrestaException(th, 25);
        }
    }   
    
    // récupérer un ProductStore par sa référence
    public ProductStore getProductStoreByReference(Integer reference){
        try{
            return (ProductStore) em.createQuery("SELECT p FROM ProductStore p WHERE p.reference = "+"\""+reference+"\"").getSingleResult();
        } catch(Throwable th){
            throw new AdopteUnPrestaException(th, 26);
        }
    }
    
    // récupérer un ProductStore par son nom
    public ProductStore getProductStoreByNom(String nom){
        try{
            return (ProductStore) em.createQuery("SELECT p FROM ProductStore p WHERE p.nom = "+"\""+nom+"\"").getSingleResult();
        } catch(Throwable th){
            throw new AdopteUnPrestaException(th, 27);
        }
    }
    
    // récupérer un ProductStore par sa description
    public ProductStore getProductStoreByDescription(String description){
        try{
            return (ProductStore) em.createQuery("SELECT p FROM ProductStore p WHERE p.description = "+"\""+description+"\"").getSingleResult();
        } catch(Throwable th){
            throw new AdopteUnPrestaException(th, 28);
        }
    }
    
    // récupérer un ProductStore par son IBAN
    public ProductStore getProductStoreByIBAN(String IBAN){
        try{
            return (ProductStore) em.createQuery("SELECT p FROM ProductStore p WHERE p.IBAN = "+"\""+IBAN+"\"").getSingleResult();
        } catch(Throwable th){
            throw new AdopteUnPrestaException(th, 29);
        }
    }      
        
    // ------------------------------------------
    // Méthodes à utiliser pour Cart
    // ------------------------------------------
    
    // ajouter un Cart
    public Cart addCart(Integer idCart, double prixTotal) {
        try{
            Cart cadie = new Cart(idCart, prixTotal);
            em.persist(cadie);
            return cadie;
        } catch(Throwable th){
            throw new AdopteUnPrestaException(th, 30);
        }
    }
    
    // Supprimer un Cart
     public void deleteCart(Cart c) {
         try{
            em.remove(em.merge(c));
         } catch(Throwable th){
            throw new AdopteUnPrestaException(th, 31);
        }
    }
     
    // récupérer la liste des Carts
    public List<Cart> getAllCart() {
        try{
            return em.createQuery("SELECT c FROM Cart c").getResultList();
        } catch(Throwable th){
            throw new AdopteUnPrestaException(th, 32);
        }
    }   
    
    // récupérer un Cart par son id
    public Cart getCartByIdCart(Integer idCart){
        try{
            return (Cart) em.createQuery("SELECT c FROM Cart c WHERE c.idCart = "+"\""+idCart+"\"").getSingleResult();
        } catch(Throwable th){
            throw new AdopteUnPrestaException(th, 33);
        }
    }
    
    // récupérer un Cart par son prix total
    public Cart getCartByPrixTotal(double prixTotal){
        try{
            return (Cart) em.createQuery("SELECT c FROM Cart c WHERE c.prixTotal = "+"\""+prixTotal+"\"").getSingleResult();
        } catch(Throwable th){
            throw new AdopteUnPrestaException(th, 34);
        }
    }
    
    // ------------------------------------------
    // Méthodes à utiliser pour Catégorie
    // ------------------------------------------
    
    // liste des catégories
    public List<Categorie> getAllCategories() {
        try{
            return em.createQuery("SELECT c FROM Categorie c").getResultList();            
        } catch(Throwable th){
            throw new AdopteUnPrestaException(th);
        }
    }
    
    // liste des développeurs parmi les prestataires
    public List<Product> getAllDevelopers(){
        try{
            return em.createQuery("SELECT p FROM Product p WHERE p.categorieidCategorie=1").getResultList();
        }catch(Throwable th){
            throw new AdopteUnPrestaException("Problème avec la récupération de la liste des développeurs",th);
        }
    }
    
    // liste des chefs de projet parmi les prestataires
    public List<Product> getAllProjectManagers(){
        try{
            return em.createQuery("SELECT p FROM Product p WHERE p.categorieidCategorie=2").getResultList();
        }catch(Throwable th){
            throw new AdopteUnPrestaException("Problème avec la récupération de la liste des chefs de projets",th);
        }
    }
    
    // liste des responsables produits parmi les prestataires
    public List<Product> getAllProductManagers(){
        try{
            return em.createQuery("SELECT p FROM Product p WHERE p.categorieidCategorie=3").getResultList();
        }catch(Throwable th){
            throw new AdopteUnPrestaException("Problème avec la récupération de la liste des responsables produit",th);
        }
    }
    
    // liste des architectes parmi les prestataires
    public List<Product> getAllArchitects(){
        try{
            return em.createQuery("SELECT p FROM Product p WHERE p.categorieidCategorie=4").getResultList();
        }catch(Throwable th){
            throw new AdopteUnPrestaException("Problème avec la récupération de la liste des architectes",th);
        }
    }
    
    // liste des coachs parmi les prestataires
    public List<Product> getAllCoachs(){
        try{
            return em.createQuery("SELECT p FROM Product p WHERE p.categorieidCategorie=5").getResultList();
        }catch(Throwable th){
            throw new AdopteUnPrestaException("Problème avec la récupération de la liste des coachs",th);
        }
    }
    
    // liste des consultants parmi les prestataires
    public List<Product> getAllConsultants(){
        try{
            return em.createQuery("SELECT p FROM Product p WHERE p.categorieidCategorie=6").getResultList();
        }catch(Throwable th){
            throw new AdopteUnPrestaException("Problème avec la récupération de la liste des consultants",th);
        }
    }
    

    // ------------------------------------------
    // Méthodes à utiliser pour Photo
    // ------------------------------------------
    
    // liste de toutes les photos
    public List<Photo> getAllPhotos()
    {
        try
        {
            return em.createQuery("SELECT f FROM Photo f").getResultList();      
        }
        catch(Throwable th)
        {
            throw new AdopteUnPrestaException("Problème avec la récupération de la liste des photos",th);
        }
    }
    
    // liste des photos d'un prestataire
    public List<Photo> getAllPhotosOfPresta(Product presta)
    {
        try
        {
            return em.createQuery("SELECT f FROM Photo f WHERE f.productidProduct=" + presta.getIdProduct() +"\"").getResultList();      
        }
        catch(Throwable th)
        {
            throw new AdopteUnPrestaException("Problème avec la récupération de la liste des photos du presta",th);
        }
    }
    
    // Ne retourne que la première photo d'un presta.
    public Photo getFirstPhotoOfPresta(Product presta)
    {
        try
        {
            Photo p_res = new Photo();
            p_res.setIdPhoto(1);
            p_res.setCheminPhoto("images//AUP_BNP//YanY_02.png");
            p_res.setProductidProduct(presta.getIdProduct());
            
            System.err.println("daoJpa -- getFirstPhotoOfPresta : presta.getNom() == " + presta.getNom());
            
            List<Photo> lp = getAllPhotosOfPresta(presta);
            if (lp != null) 
            {
                Iterator<Photo> itp = lp.iterator();
                if (itp.hasNext()) 
                {
                    p_res = itp.next();
                }
            }
            
            return p_res;
        }
        catch(Throwable th)
        {
            throw new AdopteUnPrestaException("Problème avec la récupération de la première photo du presta",th);
        }
    }
}
